package com.beantools.factory.format;

import com.beantools.constants.SingleChar;
import com.beantools.util.StringUtil;

import java.io.Serializable;
import java.util.Scanner;

import static com.beantools.constants.MainASCCode.*;
import static com.beantools.constants.SingleChar.*;
import static com.beantools.util.StringUtil.*;

/**
 * 这是json字符串格式化器。调用者需要将json字符串格式化成json字符串。
 * 或者，将已格式化的json字符串转化为其他json字符串
 *
 * @author baoya
 * @version 1.0
 * @since 1.1.o
 */
public class JsonFormat implements Serializable {

    private static final long serialVersionUID = 1804719694808870799L;


    /**
     * 调用者需要格式化的json对象转化为非格式化的json字符串，比如
     * <pre>
     *   {
     *       "key": "WEDNESDAY",
     *       value": "星期三"
     *   },
     * </pre>
     * 将其转化为这种格式的字符串：{ "key": "WEDNESDAY",value": "星期三"}
     *
     * @return 非格式化的StringBuilder类型的字符串
     */
    public static String noFormatJSON(String json) {
        if (isBlank(json)) {
            return null;
        }
        if (json.startsWith(EN_DOUBLE_QUOTATION)) {
            json = json.substring(1);
        }
        if (json.endsWith(EN_DOUBLE_QUOTATION)) {
            json = json.substring(0, json.length() - 1);
        }
        Scanner scanner = new Scanner(json);
        StringBuilder noFormat = new StringBuilder();
        while (scanner.hasNext()) {
            noFormat.append(scanner.next());
        }
        return new String(noFormat);
    }

    /**
     * 这是格式化json字符串的静态方法。在进行格式化之前，其内部会有去除空格的操作
     * 你可以通过类直接调用该方法，比如：
     * <pre>
     *      String json = "{'  english  ': '  WEDNESDAY  ','chinese': '星期三'}";
     *      System.out.println(format(String jsonStr));
     * </pre>
     *
     * @return 格式化后的json字符串
     */
    public static String format(String json) {
        if (isEmpty(json)) {
            return "";
        }
        json = StringUtil.replaceAll(json, NULL_OP, BLANK_OP);
        StringBuilder sb = new StringBuilder();
        //        当前字符
        char current = CHAR_EXIT;
//        上一个字符
        char previous = current;
//       缩进个数
        int indent = 0;
//        是否包含括号，比如 { [
        boolean isInQuotationMarks = false;
        for (int i = 0; i < json.length(); i++) {
            previous = current;
            current = json.charAt(i);
            switch (current) {
                case ASC_DOUBLE_QUOTATION:
                    if (previous != ASC_BACKSLASH) {
                        isInQuotationMarks = !isInQuotationMarks;
                    }
                    sb.append(current);
                    break;
                case ASC_LEFT_BRACE:
                case ASC_LEFT_BRACKETS:
                    sb.append(current);
                    if (!isInQuotationMarks) {
                        sb.append(LINE_FEED_OP);
                        indent++;
                        addIndentBlank(sb, indent);
                    }
                    break;
                case ASC_RIGHT_BRACE:
                case ASC_RIGHT_BRACKETS:
                    if (!isInQuotationMarks) {
                        sb.append(LINE_FEED_OP);
                        indent--;
                        addIndentBlank(sb, indent);
                    }
                    sb.append(current);
                    break;
                case ASC_SERIES_COMMA_OP:
                    sb.append(current);
                    if (previous != ASC_BACKSLASH && !isInQuotationMarks) {
                        sb.append(LINE_FEED_OP);
                        addIndentBlank(sb, indent);
                    }
                    break;
                default:
                    sb.append(current);
            }
        }
        return sb.toString();
    }

    /**
     * 该方法是添加空白字符的个数，也就是缩进个数
     *
     * @param jsonBuilder 存放需要缩进的json字符串
     * @param indent      缩进个数
     */
    public static void addIndentBlank(StringBuilder jsonBuilder, int indent) {
        if (isNotBlank(jsonBuilder) && indent > 0) {
            for (int i = 0; i < indent; i++) {
                jsonBuilder.append(SingleChar.DOUBLE_SPACE);
            }
        }
    }
}
